#include "common.h"

/*------------------------------------------------------------------
I must say:
     the type play an important role in this function.
     0bit:1,return immediately;0,wait
     1bit:1,not neglect  the signals before the signal wanted.0,neglect the signals
     2bit:1,not delete the wanted signal ,0 ,delete the signal wanted
-------------------------------------------------------------------*/
S4B Wait(PSIGNAL psignal,U4B type)
{
    U4B signalget=WhoRunning->p_signalget;
    while(((signalget)+1)%(WhoRunning->p_signallimit)!=(WhoRunning->p_signalplace))
    {
         (signalget)=(signalget+1)%(WhoRunning->p_signallimit);
                                                                                             //   Print("get:%#0cX\n\n",WhoRunning->p_signalget);
         if((WhoRunning->p_psignal[signalget]).sourcepid==psignal->sourcepid && 
            (WhoRunning->p_psignal[signalget]).signal   ==psignal->signal)
         {
              WhoRunning->p_signalreturn=(WhoRunning->p_psignal[signalget]).returnvalue;
			  WhoRunning->p_waittick    =psignal->dt;
			  WhoRunning->p_waitsignal  =(WhoRunning->p_psignal[signalget]).signal;
			  WhoRunning->p_waitsource	=(WhoRunning->p_psignal[signalget]).sourcepid;
			  
              if((((U4B)type)&((U4B)4))==(U4B)0)/*delete the wanted signal*/
              {
                  WhoRunning->p_psignal[signalget].signal=SIGNAL_INVALID;
              }
			  if((((U4B)type)&((U4B)2))==(U4B)0)/*neglect the previous signals*/
			  {
			     WhoRunning->p_signalget=signalget;
			  }
			  else /*not neglect the previous signals*/
			  {
			     if(WhoRunning->p_psignal[(WhoRunning->p_signalget)].signal==SIGNAL_INVALID)
				 {
				     (WhoRunning->p_signalget)=(WhoRunning->p_signalget+1)%(WhoRunning->p_signallimit);
				 }
			  }
			  return ARTIST_ERROR_OK;
	     }


		 
         if(psignal->sourcepid==PID_ANYVALID)
         {
             if(psignal->signal==SIGNAL_ANY)
             {
                  WhoRunning->p_signalreturn=(WhoRunning->p_psignal[signalget]).returnvalue;
				  WhoRunning->p_waitsignal  =(WhoRunning->p_psignal[signalget]).signal;
				  WhoRunning->p_waitsource  =(WhoRunning->p_psignal[signalget]).sourcepid;
				  WhoRunning->p_waittick    =psignal->dt;
				  if((((U4B)type)&((U4B)4))==(U4B)0)/*delete the wanted signal*/
                  {
                      WhoRunning->p_psignal[signalget].signal=SIGNAL_INVALID;
                  }
				  if((((U4B)type)&((U4B)2))==(U4B)0)/*neglect the previous signals*/
				  {
					 WhoRunning->p_signalget=signalget;
				  }
				  else /*not neglect the previous signals*/
				  {
					 if(WhoRunning->p_psignal[(WhoRunning->p_signalget)].signal==SIGNAL_INVALID)
					 {
					     (WhoRunning->p_signalget)=(WhoRunning->p_signalget+1)%(WhoRunning->p_signallimit);
					 }
				  }
				  return ARTIST_ERROR_OK;
			 }		 
			 
             if((psignal->signal)==(WhoRunning->p_psignal[signalget]).signal)
             {
				 WhoRunning->p_signalreturn=(WhoRunning->p_psignal[signalget]).returnvalue;
				 WhoRunning->p_waitsignal  =(WhoRunning->p_psignal[signalget]).signal;
				 WhoRunning->p_waitsource  =(WhoRunning->p_psignal[signalget]).sourcepid;
				 WhoRunning->p_waittick    =psignal->dt;
				 
				 if((((U4B)type)&((U4B)4))==(U4B)0)/*delete the wanted signal*/
				 {
					 WhoRunning->p_psignal[(signalget)].signal=SIGNAL_INVALID;
				 }
				 
				 if((((U4B)type)&((U4B)2))==(U4B)0)/*neglect the previous signals*/
				 {
					WhoRunning->p_signalget=signalget;
				 }
				 else /*not neglect the previous signals*/
				 {
					if(WhoRunning->p_psignal[(WhoRunning->p_signalget)].signal==SIGNAL_INVALID)
					{
					    (WhoRunning->p_signalget)=(WhoRunning->p_signalget+1)%(WhoRunning->p_signallimit);
				    }
				 }
				 return ARTIST_ERROR_OK;
			 }
         }
		 
         if(psignal->sourcepid==(WhoRunning->p_psignal[signalget]).sourcepid )
         {
            if(psignal->signal==SIGNAL_ANY)
            {
				WhoRunning->p_signalreturn=(WhoRunning->p_psignal[signalget]).returnvalue;
				WhoRunning->p_waitsignal  =(WhoRunning->p_psignal[signalget]).signal;
				WhoRunning->p_waitsource  =(WhoRunning->p_psignal[signalget]).sourcepid;
				WhoRunning->p_waittick	  =psignal->dt;
				
				if((((U4B)type)&((U4B)4))==(U4B)0)/*delete the wanted signal*/
				{
					WhoRunning->p_psignal[(signalget)].signal=SIGNAL_INVALID;
				}
				if((((U4B)type)&((U4B)2))==(U4B)0)/*neglect the previous signals*/
				{
				   WhoRunning->p_signalget=signalget;
				}
				else /*not neglect the previous signals*/
				{
				   if(WhoRunning->p_psignal[(WhoRunning->p_signalget)].signal==SIGNAL_INVALID)
				   {
				      (WhoRunning->p_signalget)=(WhoRunning->p_signalget+1)%(WhoRunning->p_signallimit);
				   }
				}
			   return ARTIST_ERROR_OK;
			}
            if((WhoRunning->p_psignal[(signalget)]).signal==psignal->signal)
            {
				WhoRunning->p_signalreturn=(WhoRunning->p_psignal[signalget]).returnvalue;
				WhoRunning->p_waitsignal  =(WhoRunning->p_psignal[signalget]).signal;
				WhoRunning->p_waitsource  =(WhoRunning->p_psignal[signalget]).sourcepid;
				WhoRunning->p_waittick	  =psignal->dt;
				
				if((((U4B)type)&((U4B)4))==(U4B)0)/*delete the wanted signal*/
				{
					WhoRunning->p_psignal[(signalget)].signal=SIGNAL_INVALID;
				}
				if((((U4B)type)&((U4B)2))==(U4B)0)/*neglect the previous signals*/
				{
				   WhoRunning->p_signalget=signalget;
				}
				else /*not neglect the previous signals*/
				{
				   if(WhoRunning->p_psignal[(WhoRunning->p_signalget)].signal==SIGNAL_INVALID)
				   {
				       (WhoRunning->p_signalget)=(WhoRunning->p_signalget+1)%(WhoRunning->p_signallimit);
				   }
				}
				 return ARTIST_ERROR_OK;
		    }
         }
    }   
	if((((U4B)type)&((U4B)2))==(U4B)0)/*neglect the previous signals*/
	{
	   WhoRunning->p_signalget=signalget;
	}
	else /*not neglect the previous signals*/
	{
	   if(
	   	  (WhoRunning->p_psignal[(WhoRunning->p_signalget)].signal==SIGNAL_INVALID) &&
	   	  (((WhoRunning->p_signalget)+1)%(WhoRunning->p_signallimit)!=(WhoRunning->p_signalplace))
	   	  )
	   {(WhoRunning->p_signalget)=(WhoRunning->p_signalget+1)%(WhoRunning->p_signallimit);}
	}
	if((((U4B)type)&((U4B)1))!=(U4B)0)/*not find the signal,and return back immediately.*/
    {
        return ARTIST_ERROR_SIGNALNOTFOUND;
    }
	
    WhoRunning->p_waitsource=psignal->sourcepid;
    WhoRunning->p_waitsignal=psignal->signal;
    WhoRunning->p_waittick=psignal->dt;
    WhoRunning->p_state=STATE_WAIT;
   // Print("\n%s wait %X:%X\n",WhoRunning->p_name,psignal->sourcepid,psignal->signal);
    Schedule();
    return ARTIST_ERROR_OK;
}
S4B WaitSignal(PSIGNAL psignal)
{
   S4B value;
   PCBITEM p;
   SystemCallInterrupt((U4B)SYSCALL_WAITSIGNAL,(U4B)psignal,NULL,(U4B)&value);
   p.pid=MYSELF;
   p.type=PCB_SIGNALRETURN;
   GetPCBITEM(&p);
   psignal->returnvalue=p.pvalue;
   p.type=PCB_WAITTICK;
   GetPCBITEM(&p);
   psignal->dt=p.pvalue;
   p.type=PCB_WAITSIGNAL;
   GetPCBITEM(&p);
   psignal->signal=p.pvalue;
   p.type=PCB_WAITSOURCE;
   GetPCBITEM(&p);
   psignal->sourcepid=p.pvalue;
   return value;
}
